package squareBorderPackage;

import be.kuleuven.cs.som.annotate.Basic;

/**
 * A class of doors involving two squares in two opposed directions.
 * 
 * @author	Jessa Bekker & Esther Alberts
 * @version	2.0
 */
public class Door extends Border {

	/**
	 * Initialize this new door with given state (open or closed).
	 * 
	 * @param 	opened
	 *          The initial value for the open state of this new door.
	 * @param	square
	 * 			The square to which this door must be attached.
	 * @param	direction
	 * 			The direction in which this door must be attached to the given square.			
	 */
	public Door(boolean opened, Square square, Direction direction) {
		super(square, direction);
		this.opened = opened;
	}

	/**
	 * Return whether this wall is slippery or not.
	 */
	@Override
	public boolean getSlippery() {
		return false;
	}

	/**
	 * Method returning whether this Door is an obstacle or not.
	 * 
	 * @return 	... 
	 * 			|result==!opened
	 */
	@Override
	public boolean isObstacle() {
		if (opened == true)
			return false;
		return true;
	}

	/**
	 * @return 	This border if the other border is not effective 
	 * 			| if (other == null) 
	 * 			| then (result == this)
	 * @return 	The other border if the other border is a door and this door is opened. 
	 * 			|if (other instanceof Door && this.isOpened()) 
	 * 			| then (result == other)
	 * @return 	This border if the other Border is a Door and this door is not opened. 
	 * 			|if (other instanceof Door && ! this.isOpened()) 
	 * 			| then (result == this)
	 * @return 	This border if the other border is a open border. 
	 * 			|if (other instanceof OpenBorder) 
	 * 			| then (result == this)
	 * @return 	The strongest border of the other border and this border in all
	 *         	other cases. 
	 *         	|if (! (other == null || 
	 *         	| other instanceof Door ||
	 *         	| other instanceof OpenBorder)) 
	 *         	| then (result == other.getStrongestBorder(this)
	 */
	@Override
	public Border getStrongestBorder(Border other) {
		if (other == null)
			return this;
		if (other instanceof Door) {
			if (this.isOpened())
				return other;
			return this;
		}
		if (other instanceof OpenBorder)
			return this;
		return other.getStrongestBorder(this);
	}

	/**
	 * Split this border in two borders.
	 * 
	 * @return	...
	 * 			| result[0].getSquareAt(getSquareDirections()[0]) = this.getSquareAt(getSquareDirections()[0])
	 * 			| && result[0].getSquareAt(getSquareDirections()[1]) = null
	 * 			| && result[1].getSquareAt(getSquareDirections()[1]) = this.getSquareAt(getSquareDirections()[0])
	 * 			| && result[1].getSquareAt(getSquareDirections()[0]) = null
	 * 			| && result[0].isOpened() == this.isOpened()
	 * 			| && result[1].isOpened() == this.isOpened()
	 */
	@Override
	public Door[] split() {
		Square square = getSquareAt(getSquareDirections()[0]);
		removeSquareAt(getSquareDirections()[0]);
		Door other = new Door(isOpened(), square, getSquareDirections()[0]);
		Door[] borders = new Door[2];
		borders[0] = other;
		borders[1] = this;
		return borders;
	}

	/**
	 * Return whether the door is opened or not.
	 */
	@Basic
	public boolean isOpened() {
		return opened;
	}

	/**
	 * Set whether the door is opened or not.
	 * 
	 * @param 	opened
	 *          the boolean referencing whether the door is opened or not
	 * @effect	If this door was closed and the new door is opened, merge the
	 * 			squares of this door.
	 * 			| if (opened && !wasOpened)
	 *			|	then (getSquares()[0].mergeWith(getSquares()[1]))
	 * @effect	If this door was opened and the new door is closed,
	 * 			update the spaces of the squares of this door.
	 * 			| if (!opened && wasOpened)
	 * 			|	then (for each square of getSquares() :
	 * 			|				square.updateSpace())
	 */
	public void setOpened(boolean opened) {
		boolean wasOpened = this.opened;
		this.opened = opened;
		if (opened && !wasOpened)
			((AccessibleSquare) getSquares()[0]).mergeWith((AccessibleSquare) getSquares()[1]);
		if (!opened && wasOpened)
			for(Square square : getSquares())
				square.updateSpace();
	}

	/**
	 * Variable registering whether the door is opened or not.
	 */
	private boolean opened;
}
